为了学习下分布式技术,先学习下 Nginx 反向代理服务器,在学习过程中,顺便还巩固了计算机系统的一些知识,同时,网上关于在 Linux 上配置 Nginx 的教程已经很多了,奈何本人对 Linux 并不是很熟悉,同时现在写的网站大多还是发布在 IIS 上面的,因此本教程主要讲解在 Windows 下配置 Nginx 反向代理服务器。

Windows下配置 Nginx 反向代理服务器

什么是代理?

在学习 Nginx 前,先补充下代理服务器的概念:

代理服务器:一般指的是局域网内部的机器通过代理服务器发送请求到互联网上的服务器,代理服务器一般作用在客户端。应用方面比如:科学上网工具、Nginx。

完整的代理请求流程:客户端首先与代理服务器创建连接,然后根据代理服务器所使用的代理协议请求对目标服务器创建连接或者获得目标服务器的指定资源。代理服务器位于客户端和 Web 服务器之间,扮演中间人的角色,HTTP 的代理服务器既是 Web 服务器又是 Web 客户端,而代理服务器则是介于客户端与 Web 服务器中间的另一台服务器。有了代理服务器之后,客户端发过来的请求不再直接发向 Web 服务器,而是发向了代理服务器,由代理服务器发出请求,取回请求资源后,返回给客户端。

image
image

正向代理服务器: 位于客户端和原始服务器之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指向原始服务器,然后代理向原始服务器转交请求并将获取到的内容返回给客户端。客户端必须进行一些特别的设置才能使用正向代理。

反向代理服务器: 在服务端接收客户端的请求,然后把请求分发给具体的服务器进行处理,再将服务器的响应结果返回给客户端。Nginx 就是其中一种反向代理服务器软件。

Nginx

Nginx 是俄罗斯 Igor Sysoev 开发的一款高性能的HTTP和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器,Nginx 本身就可以托管网站,进行HTTP服务处理,也可以作为反向代理服务器使用。

Nginx特点

  • 跨平台:Nginx 可以在大多数 Unix 内核的系统中编译运行,也有 Windows 的移植版本。
  • 配置简单:配置风格和程序开发相近
  • 高并发、非阻塞:复制数据时,磁盘 I/O 的第一阶段是非阻塞的。官方测试能够支撑5万并发连接(实际生产环境中能跑到 2万~3万 并发连接数)
  • 事件驱动:通信机制采用 epoll 模型,支撑更大的并发连接

除此之外,Nginx 还有其他业务上的优势:

  1. Nginx 代理和后端 Web 服务器间无需长连接
  2. 接收用户请求是异步的,即先将用户的请求全部接收下来,再一次性发送后端 Web 服务器,极大减轻后端Web 服务器的压力
  3. 发送响应报文时,一遍接收来自后端 Web 服务器的数据,一边发送个客户端
  4. 网络依赖性低。Nginx 对网络的依赖程度非常低,从理论上来说,只要能够 Ping 通就可以实施负载均衡,而且可以有效区分内网和外网流量。
  5. 支持服务器检测。Nginx 能够根据应用服务器处理页面返回的状态码,超时信息等检测服务器是否出现故障,并及时返回错误的请求,重新提交到其他节点上。

Nginx事件处理机制

通信机制采用epoll模型,支持更大的并发连接。

  • master/worker 结构:一个 master 进程,生成多个 worker 进程
  • 内存消耗小:并发处理大并发的请求,内存消耗非常小。在3万并发连接下,开启的1个 Nginx 进程才消耗150MB 内存(15MB*10=150MB)
  • 成本低:Nginx 作为开源软件,可以免费使用,而硬件负载均衡交换机则需要十多万甚至几十万人民币
  • 内置的健康检查功能:如果 Nginx Proxy 后端的某台 Web 服务器宕机了,就不会影响前端访问
  • 节省带宽:支持GZIP压缩,可以添加浏览器本地缓存的Header头。
  • 稳定性高:用于反向代理,宕机的概率微乎其微。

Nginx 内部模型

Nginx是以多进程的方式来工作的。当然 nginx 也是支持多线程的方式的,仅仅是我们主流的方式还是多进程的方式,也是nginx的默认方式。 nginx 採用多进程的方式有诸多优点。

  1. nginx 在启动后,会有一个master进程和多个 worker 进程。master 进程主要用来管理 worker 进程,包括:接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的执行状态,当 worker 进程退出后(异常情况下),会自己主动又一次启动新的 worker 进程。而主要的网络事件。则是放在 worker 进程中来处理了 。多个 worker 进程之间是对等的,他们同等竞争来自 client 的请求。各进程互相之间是独立的 。一个请求,仅仅可能在一个 worker 进程中处理,一个 worker 进程,不可能处理其他进程的请求。

    worker 进程的个数是能够设置的,一般我们会设置与机器 cpu 核数一致,这里面的原因与 nginx 的进程模型以及事件处理模型是分不开的 。

  2. Master 接收到信号以后如何进行处理(./nginx -s reload )?

    首先 master 进程在接到信号后,会先又一次载入配置文件。然后再启动新的进程。并向全部老的进程发送信号,告诉他们能够光荣退休了。

    新的进程在启动后,就開始接收新的请求,而老的进程在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的全部未处理完的请求处理完毕后,再退出 .

  3. worker 进程又是如何处理请求的呢?我们前面有提到。worker 进程之间是平等的。每一个进程,处理请求的机会也是一样的。当我们提供 80 port 的 http 服务时。一个连接请求过来,每一个进程都有可能处理这个连接,怎么做到的呢?首先,每一个 worker 进程都是从 master 进程 fork 过来,在 master 进程里面。先建立好须要 listen 的 socket 之后。然后再 fork 出多个 worker 进程,这样每一个 worker 进程都能够去 accept 这个 socket (当然不是同一个 socket ,仅仅是每一个进程的这个 socket 会监控在同一个 ip 地址与 port,这个在网络协议里面是同意的)。一般来说。当一个连接进来后。全部在 accept 在这个 socket 上面的进程。都会收到通知。而仅仅有一个进程能够 accept 这个连接,其他的则 accept 失败,这是所谓的惊群现象。

    当然,nginx 也不会视而不见,所以 nginx 提供了一个 accept_mutex 这个东西,从名字上。我们能够看这是一个加在 accept 上的一把共享锁。有了这把锁之后,同一时刻,就仅仅会有一个进程在 accpet 连接,这样就不会有惊群问题了。accept_mutex 是一个可控选项,我们能够显示地关掉。默认是打开的。当一个 worker 进程在 accept 这个连接之后,就開始读取请求。解析请求。处理请求,产生数据后,再返回给 client,最后才断开连接,这样一个完整的请求就是这种了。我们能够看到,一个请求。全然由 worker 进程来处理。并且仅仅在一个 worker 进程中处理。

  4. nginx 采用这种进程模型有什么优点呢?採用独立的进程,能够让互相之间不会影响,一个进程退出后,其他进程还在工作,服务不会中断,master 进程则非常快又一次启动新的 worker 进程。当然,worker 进程的异常退出。肯定是程序有 bug 了,异常退出。会导致当前 worker 上的全部请求失败,只是不会影响到全部请求,所以减少了风险。当然,优点还有非常多,大家能够慢慢体会。

  5. 有人可能要问了。nginx 採用多 worker 的方式来处理请求,每一个 worker 里面仅仅有一个主线程,那能够处理的并发数非常有限啊。多少个 worker 就能处理多少个并发。何来高并发呢?非也,这就是 nginx 的高明之处,nginx 採用了异步非堵塞的方式来处理请求。也就是说,nginx 是能够同一时候处理成千上万个请求的 .对于 IISserve r每一个请求会独占一个工作线程。当并发数上到几千时,就同一时候有几千的线程在处理请求了。

    这对操作系统来说。是个不小的挑战,线程带来的内存占用非常大。线程的上下文切换带来的 cpu 开销非常大。自然性能就上不去了。而这些开销全然是没有意义的。

    我们之前说过,推荐设置 worker 的个数为 cpu 的核数,在这里就非常 easy 理解了,很多其他的 worker 数,仅仅会导致进程来竞争 cpu 资源了,从而带来不必要的上下文切换。

    并且,nginx 为了更好的利用多核特性,提供了 cpu 亲缘性的绑定选项。我们能够将某一个进程绑定在某一个核上。这样就不会由于进程的切换带来 cache 的失效。

Nginx应用场景

负载均衡技术在现有网络结构智商提供了一种廉价、有效、透明的方法来扩展网络设备和服务器的带宽 、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。它有两方面的含义:首先,大量并发的访问或数据流量分担到多台节点设备上分别处理,减少用户等待相应的时间;其次,单个负载均衡的运算分担到多台节点设备上做并行处理,每个节点设备处理结束后将结果汇总,返回给用户,系统处理能力得到大幅度提高。

Nginx的使用

本文只讲解 Windows 版本的 Nginx,Linux 上的 Nginx 以后再讲

  1. 到官方网站下载 Windows 版本。下载地址
  2. 解压后,文件结构如下
  1. 修改配置文件 。打开目录 Conf,找到 nginx 核心的配置文件 nginx.conf 进行修改。

  2. 启动服务:直接运行 nginx.exe 即可。

  3. 停止服务:

    1. 启动任务管理器直接关闭进程
    2. 在 CMD 中,进入 nginx.exe 所在目录,输入 nginx -s stop
  4. 重新加载配置:

    1. 重启 nginx.exe
    2. 在 CMD 中,进入 nginx.exe 所在目录,输入 nginx -s reload

Nginx的常见配置

常见配置

Nginx集群案例

最后一步,通过一个 Demo 来演示使用 Nginx+IIS 服务器来搭建服务器集群

为了演示,创建了3个 Web 项目,然后分别部署在三台IIS服务器上,当然这个 Demo 并未做详细的业务与逻辑,只以站点的内容让其稍微有点不同以区分。而生产环境则是把相同的 Web 项目部署在不同的IIS服务器上面。

创建项目

  1. 新建一个空的 MVC 项目

  2. 添加控制器 Home

  3. 添加 Index 视图

    1
    2
    3
    4
    @{
    ViewBag.Title = "Index"
    }
    <h2>这是第1个网站</h2>
  4. 发布站点1

  5. 将发布好的站点中的View\Home\Index.cshtml内容修改为:

    1
    2
    3
    4
    @{
    ViewBag.Title = "Index"
    }
    <h2>这是第2个网站</h2>

    获得第二个站点,并发布

  6. 继续第5步,修改内容为:

    1
    2
    3
    4
    @{
    ViewBag.Title = "Index"
    }
    <h2>这是第3个网站</h2>

    获得第三个站点,并发布

  7. 修改 Nginx 的配置文件 nginx.conf

    在 http 节点上添加代码如下:

    1
    2
    3
    4
    5
    6
    7
    upstream netittest.com{
    #服务器集群名字
    server www.barteam.cn:8085 weight=1;
    server superforest.cn:8085 weight=1;
    server 127.0.0.1:8087 weight=1;
    server 127.0.0.1:8089 weight=1;
    }

    修改 http 节点上的 server 节点、 location 节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     server {
    listen 8088; #监听端口
    server_name superforest.cn;#你服务器的节点,如果是本地的话为127.0.0.1

    location / {
    #root html;
    #index index.html index.htm;
    proxy_pass http://netittest.com;
    proxy_redirect default;
    ·············
    }
  8. 启动 nginx 服务,以管理员身份,运行 CMD 窗口,进入 nginx 所在目录,启动 nginx.exe

    1
    C:\Program Files (x86)\nginx-1.14.2>nginx.exe
  9. 在浏览器输入你上面 server 中配置的 server_name 和 listen(nginx 配置文件中配置的服务器监听终结点),然后刷新浏览器,结果如下:

image
image

请注意,浏览器地址框一直未变。

其实现原理如下图所示

image
image

这个 Demo 只是为了简单演示下关于通过 Nginx 搭建集群的效果,如果换到生产环境的话,需要配置的就不止上面这些,关于其他详细的配置可以查看前文中的链接,或去百度查找其他博客。


参考资料